using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace Cpt_HotApple_v2
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        public static SpriteBatch spriteBatch;
        //Declare the tile sheet texture
        public static Texture2D tileSheet;

        //Declare a level
        Level.Level map;

        //Declare the player
        Actors.Player player;

        //Declare collision variables
        Vector2 normal;
        Vector2 collisionDist = Vector2.Zero;

        //Sound
        //SoundEffect sound;

        //Healthbar
        Texture2D mHealthBar;
        int mCurrentHealth = 100;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            //Construct the level
            map = new Cpt_HotApple_v2.Level.Level();

            //Construct the player
            player = new Cpt_HotApple_v2.Actors.Player(Content, new Vector2(Window.ClientBounds.Width, Window.ClientBounds.Height));
            //sound = Content.Load<SoundEffect>("Musik/sample"); 
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            //Load the map and tileset
            tileSheet = Content.Load<Texture2D>(@"Textures/testsheet");
            map.LoadMap("Content/Maps/test.txt");
            map.LoadTileSet(tileSheet);
            map.PopulateCollisionLayer();
            //sound.Play();

            //Load the HealthBar image from the disk into the Texture2D object
            mHealthBar = Content.Load<Texture2D>(@"Misc/healthbar");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            //Update the player
            player.Update();

            //Reset collision dist
            collisionDist = Vector2.Zero;

            //Check for collisions
            for (int i = 0; i < map.collisionRects.Count(); i++)
            {
                if (IsColliding(player.collisionRect, map.collisionRects[i]))
                {
                    //If there are multiple collision make sure we only react to the most severe
                    if (normal.Length() > collisionDist.Length())
                        collisionDist = normal;
                }
            }

            //Update the players position
            player.position.X += collisionDist.X;
            player.position.Y += collisionDist.Y;

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            //Begin the spritebatch call
            spriteBatch.Begin();

            //Draw the map
            map.DrawMap(player);
            //Draw the health for the health bar
            spriteBatch.Draw(mHealthBar, new Rectangle(this.Window.ClientBounds.Width / 2 - mHealthBar.Width / 2, 29, mHealthBar.Width, 17), new Rectangle(0, 30, mHealthBar.Width, 17), Color.Red);
            //Draw the box around the health bar
            spriteBatch.Draw(mHealthBar, new Rectangle(this.Window.ClientBounds.Width / 2 - mHealthBar.Width / 2, 29, mHealthBar.Width, 17), new Rectangle(0, 0, mHealthBar.Width, 17), Color.White);

            base.Draw(gameTime);

            //End the spritebatch call
            spriteBatch.End();

        }

        private bool IsColliding(Rectangle body1, Rectangle body2)
        {
            //Reset the normal vector
            normal = Vector2.Zero;

            //Get the centre of each body
            Vector2 body1Centre = new Vector2(body1.X + (body1.Width / 2), body1.Y + (body1.Height / 2));
            Vector2 body2Centre = new Vector2(body2.X + (body2.Width / 2), body2.Y + (body2.Height / 2));

            //Declare 2 local vectors
            Vector2 distance, absDistance;

            //xMag and yMag represent the magnitudes of the x and y components of the normal vector
            float xMag, yMag;

            //Calculate the difference in position of the two rectangles
            distance = body1Centre - body2Centre;

            //Get the combined half heights/widths of the rects
            float xAdd = ((body1.Width) + (body2.Width)) / 2.0f;
            float yAdd = ((body1.Height) + (body2.Height)) / 2.0f;

            //Calculate absDistance, according to distance
            absDistance.X = (distance.X < 0) ? -distance.X : distance.X;
            absDistance.Y = (distance.Y < 0) ? -distance.Y : distance.Y;

            //Check if there is a collision
            if (!((absDistance.X < xAdd) && (absDistance.Y < yAdd)))
                return false;

            //The magnitude of the normal vector is determined by the overlap in the rectangles.
            xMag = xAdd - absDistance.X;
            yMag = yAdd - absDistance.Y;

            //Only adjust the normal vector in the direction of the least significant overlap.
            if (xMag < yMag)
                normal.X = (distance.X > 0) ? xMag : -xMag;
            else
                normal.Y = (distance.Y > 0) ? yMag : -yMag;

            //There was a collision, return true
            return true;
        }
    }
}
